package com.dopplr.examples.modestmaps
{
    import com.dopplr.api.API;
    import com.dopplr.api.City;
    import com.dopplr.api.Traveller;
    import com.dopplr.api.Trip;
    import com.modestmaps.Map;
    import com.modestmaps.core.MapExtent;
    import com.modestmaps.extras.Distance;
    import com.modestmaps.extras.GreatCircleOverlay;
    import com.modestmaps.extras.LineStyle;
    import com.modestmaps.extras.MapControls;
    import com.modestmaps.geo.Location;
    import com.modestmaps.mapproviders.BlueMarbleMapProvider;
    
    import flash.display.LineScaleMode;
    import flash.display.LoaderInfo;
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.ErrorEvent;
    import flash.events.Event;
    import flash.events.StatusEvent;
    import flash.text.TextField;

    [SWF(backgroundColor='#ffffff')]
    public class DopplrMapCircles extends Sprite
    {
        public var api:API;
        public var map:Map;
        public var overlay:GreatCircleOverlay;

        public function DopplrMapCircles()
        {
            // I wish these were the defaults
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            // the API token is passed into Flash via flashvars in the HTML
            // to get this working you can hardcode one from http://www.dopplr.com/account/api_session_token
            // but don't distribute it in code or a swf!
            var token:String = LoaderInfo(root.loaderInfo).parameters.token;
            if (token) {
                map = new Map(stage.stageWidth, stage.stageHeight, true, new BlueMarbleMapProvider());
                map.setCenterZoom(new Location(0,0), 2);
                addChild(map);
                
                map.grid.alpha = 0;
                
                overlay = new GreatCircleOverlay(map);                
                map.addChildAt(overlay, map.getChildIndex(map.markerClip));
                
                addChild(new MapControls(map,true,true));
                                
                stage.addEventListener(Event.RESIZE, onStageSize);
                stage.addEventListener(Event.FULLSCREEN, onStageSize);
                
                api = new API(token);
                api.addEventListener(ErrorEvent.ERROR, onAPIError);
                api.addEventListener(StatusEvent.STATUS, onAPIStatus);
                
                // travellerLoaded is a function, below, which accepts a com.dopplr.api.Traveller instance
                api.loadAuthenticatedUser(travellerLoaded);
                
            }
            else {
                var text:TextField = new TextField();
                text.name = 'error';
                text.text = "problem initializing dopplr access: no token found";
                text.width = text.textWidth + 4;
                addChild(text);
            }
        }

        /** now we know about you, but we don't know where you're going yet */
        public function travellerLoaded(traveller:Traveller):void
        {
            api.loadTravellerTrips(traveller, drawTripsForTraveller);
        }
         
        /** now we know where you're going */       
        public function drawTripsForTraveller(traveller:Traveller):void
        {
            var dots:Array = []; // list of city/departures from the user's trips
            var extent:MapExtent = new MapExtent();
            
            // create a great-circle arc for each trip
            for each (var trip:Trip in traveller.trips) {
                
                if (trip.city == trip.departure) continue; // skip untravel
                
                var start:Location = new Location(trip.departure.latitude, trip.departure.longitude);
                var end:Location = new Location(trip.city.latitude, trip.city.longitude);
                
                // make longer lines thicker in the middle (GreatCircleOverlay handles the rest of this)
                var thick:Number = Math.pow(Distance.approxDistance(start,end) / (0.25 * 2 * Math.PI * 6378000), 0.2);
                var arcExtent:MapExtent = overlay.addGreatCircle(start, end, new LineStyle(2 * thick, 0xcc0000, 1.0, false, LineScaleMode.NONE));
                
                // grow the map extent to fit the arc inside
                extent.encloseExtent(arcExtent);
                
                // add city and departure city to dots array
                if (dots.indexOf(trip.departure) < 0) dots.push(trip.departure);
                if (dots.indexOf(trip.city) < 0) dots.push(trip.city);
                
            }
            
            // add a marker for each city/departure
            for each (var dot:City in dots) {
                var s:Shape = new Shape();
                s.graphics.lineStyle(1,0x000000,1,true);
                s.graphics.beginFill(0xffffff);
                s.graphics.beginFill(0xcc0000);
                s.graphics.drawCircle(0,0,3);
                s.graphics.endFill();
                var location:Location = new Location(dot.latitude, dot.longitude);
                map.putMarker(dot.geonameId.toString(), location, s);
            }
            
            // zoom the map to fit all the arcs in
            map.setExtent(extent);
        }

        /** add a textfield with an error, reuse the text field if possible */
        public function onAPIError(error:ErrorEvent):void
        {
            var text:TextField = this.getChildByName('error') as TextField;
            if (!text) {
                text = new TextField();
                text.name = 'error';
                text.textColor = 0x000000;
                text.background = true;
                text.backgroundColor = 0xffff00;
                addChild(text);                
            }
            text.text = "Error: " + error.text;
            text.width = text.textWidth + 4;
            text.height = text.textHeight + 4;
        }
        
        /** add a textfield with a status, reuse the text field if possible */
        public function onAPIStatus(event:StatusEvent):void
        {
            var status:TextField = this.getChildByName('status') as TextField;
            if (!status) {
                status = new TextField();
                status.name = 'status';
                status.textColor = 0x000000;
                status.background = true;
                status.backgroundColor = 0xffffff;
                addChild(status);                
            }
            status.text = event.code;
            status.width = status.textWidth + 4;
            status.height = status.textHeight + 4;
            status.x = 15;
            status.y = stage.stageHeight - status.height - 15;
        }
        
        /** make sure things are in place */
        private function onStageSize(event:Event):void
        { 
            map.setSize(stage.stageWidth, stage.stageHeight); 
            var status:TextField = this.getChildByName('status') as TextField;
            if (status) {
                status.x = 15;
                status.y = stage.stageHeight - status.height - 15;
            }
        }
        
    }
}


